//
//  main.m
//  OC07_内存管理
//
//  Created by Hanlingyu on 16/7/12.
//  Copyright © 2016年 ltq. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Man.h"
int main(int argc, const char * argv[]) {
    // 内存问题:
    // 一. 内存泄露 / 内存溢出:
    //      内存过多导致溢出, 产生Crash
    // 二. 野指针(过度释放):
    //      指针指向未知区域, 指向一块被释放的内存
    // 内存管理方式:
    // 1. 垃圾回收机制: 只有Mac存在
    // iOS
    // 2. MRC: 手动管理引用计数
    // 3. ARC: 自动管理引用计数 (现在常用)
    // 注意: ARC基于MRC进行管理, 系统帮程序员添加了内存管理的内容
    
    
    // retain, alloc, copy需要进行内存管理
    // eg:
//    NSObject *objc = [[NSObject alloc] init];
//    [objc retain];
//    [objc release];
//    [objc release];
//    
//    NSObject *objc1 = [NSObject new];
    
    // 1. MRC:
    // 内存管理: 引用计数(计数器)
    // 有retain, allow, copy需要对引用计数 +1
    // 有release, autorelease 会对引用计数 -1
    // 当对象的引用计数为0的时候, 系统会调用对应的dealloc方法
    
    
    // 注意: 内存管理, 对对象操作完成后, 再进行释放
    Man *man = [[Man alloc] init];
    NSLog(@"%ld", man.retainCount);
    [man retain];
    
    [man release];
    NSLog(@"%ld", man.retainCount);
    
    // 集合类型, 会对对象进行引用计数
    // addObject 对对象进行引用计数 + 1;
    // removeObject 对对象进行引用计数 - 1;
    NSMutableArray *array = [NSMutableArray arrayWithObjects:man, nil];
    NSLog(@"向数组中添加后的引用计数: %ld", man.retainCount);
    [array removeAllObjects];
    NSLog(@"从数组中移除后的引用计数: %ld", man.retainCount);
    
    // 2. ARC:
    // strong(ARC, 引用计数 +1) weak(应用于对象类型(NSObject的子类), 弱引用, 在对象被释放的时候, 会自动置空)
    // retain(MRC, 引用计数 -1)
    // copy(拷贝, 把对象拷贝一份, 原来的引用计数不变, 新的 + 1)
    // assgin (应用于简单的数据类型, 不会产生引用计数)
    
    
    // 协议(三步)
    // 1. 声明协议, 声明协议方法
    // 2. 签订协议
    // 3. 实现协议方法
    [man sayHello];
    [man retain];
    
    // 如果想实现对象的拷贝
    // 1. 签订协议NSCopying
    // 2. 实现协议方法copyWithZone;
    Man *newMan = [man copy];
    NSLog(@"newMan: %@ - oldMan: %@", newMan, man);
    
    
    newMan.name = @"韩旭";
    newMan.sexual = @"女";
    
    
    // KVC Key - Value - Coding 键值编码 间接访问成员的方式
    // valueForKey
    // valueForKeyPath
    // setValue: forKey:
    // 色图Value: forKeyPath;
    id name = [newMan valueForKey:@"name"];
    [newMan setValue:@"徐康" forKey:@"name"];
    NSLog(@"%@", name);
    
    
    Man *gayMan = [[Man alloc] init];
    gayMan.gayBoy = newMan;
    
    id boyName = [gayMan valueForKeyPath:@"gayBoy.name"];
    NSLog(@"boyName: %@", boyName);
    [gayMan release];
    
    
    [gayMan setValue:@"李四" forKeyPath:@"gayBoy.name"];
    NSLog(@"%@", gayMan.gayBoy.name);
    
    
//    NSDictionary *dic = [NSDictionary dictionary];
//    [dic setValue:@"张三" forKeyPath:@"name"];
    
    NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:@"123456789", @"id", @"逗比", @"description", nil];
    Man *dicMan = [[Man alloc] init];
    [dicMan setValuesForKeysWithDictionary:dic];
    
    // 加在Build Phases下的编译source下
    // 如果在ARC工程下使用MRC的文件
    // -fno-objc-arc
    // 在MRC工程下使用ARC的文件
    // -fobjc-arc
    
    
    
    return 0;
}
